#include<string.h>
#include<time.h>
#include<winsock2.h>
#include<stdio.h>
#include<iostream>
using namespace std;
class FileGet{
private:
	char* pbuffer;
public:
	FileGet()
	{
		pbuffer=NULL;
	}
	~FileGet()
	{
		if(pbuffer!=NULL)
		{
			free(pbuffer);
			pbuffer=NULL;
		}
	}
	int getFileLen(const char* fileName)
	{
		int len=0;
		FILE* fp=fopen(fileName,"rb");
		if(fp==NULL)
			return -1;
		fseek(fp,0,SEEK_END);
		len=ftell(fp);
		fclose(fp);
		return len;
	}
	bool getFileMsg(const char* fileName,char* buffer,unsigned int bufferLen)
	{
		int i=0,len=0;
		len=this->getFileLen(fileName);
		FILE* fp=fopen(fileName,"rb");
		if(fp==NULL)
			return false;
		for(i=0;i<len&&i<bufferLen;i++)
			buffer[i]=fgetc(fp);
		buffer[i+1]=0;
		fclose(fp);
		return true;
	}
	bool fileStrstr(const char* fileName,const char* strFind)
	{
		int len=0;
		char* pstr=NULL;
		len=this->getFileLen(fileName);
		if(pbuffer!=NULL)
		{
			free(pbuffer);
			pbuffer=NULL;
		}
		FILE* fp=fopen(fileName,"r");
		if(fp==NULL)
			return false;
		pbuffer=(char*)malloc(sizeof(char)*(len+10));
		char* ptemp=pbuffer;
		if(pbuffer==NULL)
			return false;
		memset(pbuffer,0,sizeof(char)*(len+5));
		if(false==this->getFileMsg(fileName,pbuffer,sizeof(char)*(len+10)))
			return false;
		while((*ptemp<65||*ptemp>122)&&ptemp<pbuffer+sizeof(char)*len)
			ptemp++;
		pstr=strstr(ptemp,strFind);
		if(pbuffer!=NULL)
		{
			free(pbuffer);
			pbuffer=NULL;
		}
		fclose(fp);
		if(pstr!=NULL)
			return true;
		else
			return false;
		return false;
	}
	static bool writeToFile(const char* fileName,const char* buffer,unsigned int writeLen)
	{
		FILE* fp=fopen(fileName,"wb+");
		if(fp==NULL)
			return false;
		for(unsigned int i=0;i<writeLen;i++)
			fputc(buffer[i],fp);
		fclose(fp);
		return true;
	}
};
class DownloadFile{
private:
	char url[256];
	char urlTop[100];
	char urlEnd[256];
	char fileName[100];
	time_t tbegin;
	time_t tend;
public:
	DownloadFile()
	{
		memset(url,0,256);
		memset(fileName,0,100);
		memset(urlTop,0,100);
		memset(urlEnd,0,256);
		tbegin=0;
		tend=0;
	}
	bool startDownload(const char* httpAdd,int* len,int* rate,const char* urlDownload,const char* toFileName=NULL)
	{
		char* ptemp=NULL;
		strcpy(url,urlDownload);
		if(strstr(urlDownload,"http://")==NULL&&strstr(urlDownload,"https://")==NULL&&httpAdd!=NULL)
			sprintf(url,"http://%s%s",httpAdd,urlDownload);
		if(toFileName!=NULL)
			strcpy(fileName,toFileName);
		else
		{
			if((ptemp=strrchr(urlDownload,'/'))==NULL)
				return false;	
			else
				sscanf(ptemp+1,"%s",fileName);
		}
//		DeleteUrlCacheEntry(url);
		tbegin=time(NULL);
		long status=URLDownloadToFile(0,url,fileName,0,NULL);
		if(status==0)
		{
			tend=time(NULL);
			FILE* fp=fopen(fileName,"rb");
			if(fp==NULL)
			{
				*len=0;
				*rate=0;
				return false;
			}
			fseek(fp,0,SEEK_END);
			*len=(int)(ftell(fp)/1024);
			fclose(fp);
			*rate=(int)((*len)/(tend-tbegin));
			return true;	
		}
		*len=0;
		*rate=0;
		return false;	
	}	
	void dealUrl(const char* url,char* urlTop,char* urlEnd)
	{
		char* ptemp=NULL;
		int len=0;
		if((ptemp=strstr(url,"http://"))==NULL)
		{
			if(strstr(url,"https://")!=NULL)
			{
				sscanf(url+8,"%[^/]",urlTop);
				len=strlen(urlTop);
				sscanf(url+len+8,"%s",urlEnd);
				return;
			}
			else
			{
				sscanf(url,"%[^/]",urlTop);
				len=strlen(urlTop);
				sscanf(url+len,"%s",urlEnd);
				return;
			}
		}
		else
		{
			sscanf(url+7,"%[^/]",urlTop);
			len=strlen(urlTop);
			sscanf(url+len+7,"%s",urlEnd);
		}
	}
	void createAsk(const char* domain,char* pask)
	{
		dealUrl(domain,urlTop,urlEnd);
		sprintf(pask,"GET %s HTTP/1.1\r\n"
			"Host:%s\r\n"
			"Connection: Close\r\n\r\n",urlEnd,urlTop);
	}
	void getTopAndEnd(char* top,char* end)
	{
		strcpy(top,urlTop);
		strcpy(end,urlEnd);
	}
	char* getUrl(const char* findFromFile,const char* findRec,char* url,const char* pbegin,const char* pend)
	{
		int i=0;
		char* begin=NULL,*end=NULL,*ptemp=NULL;
		const char* findFrom=findFromFile;
		while(1)
		{
			if((ptemp=strstr(findFrom,findRec))==NULL)
				return NULL;
			if(*(ptemp-1)!='.')
			{
				findFrom+=strlen(findRec);
				continue;
			}
			if((*(ptemp+strlen(findRec))!='\"')&&(*(ptemp+strlen(findRec))!=' '))
			{
				findFrom+=strlen(findRec);
				continue;
			}
			break;				
		}
		begin=ptemp;
		end=ptemp;
		while(*(--begin)!='\"'&&(*begin)!='\''&&(*begin)!=';'&&(*begin)!='='&&begin>pbegin);
		begin++;
		while(*(++end)!='\"'&&(*end)!='\''&&(*end)!=';'&&(*end)!='='&&(end<pend-5));
		for(char* pi=begin;pi<end;pi++)
			url[i++]=*pi;
		url[i]=0;
		return ptemp+strlen(findRec);	
	}
	void reptile(const char* from,const char* kind,int* plen,int* prate)
	{
		const char* ptemp=from;
		while((ptemp=this->getUrl(ptemp,kind,url,from,from+strlen(from)))!=NULL)
			this->startDownload(urlTop,plen,prate,url);
	}
};
class ClientTcpIp{
private:
	WSADATA wsa;//apply for api
	SOCKET sock;//myself
	SOCKADDR_IN addrC;//server information
	char ip[20];//server Ip
	char sen[200];//what you send
	char rec[200];//what you get
	char* hostip;//host ip
	char* hostname;//host name
public:
	ClientTcpIp(const char* hostIp,int port=5200)
	{
		if(WSAStartup(MAKEWORD(2,2),&wsa)!=0)
			exit(0);
		memset(ip,0,20);
		if(hostIp!=NULL)
			strcpy(ip,hostIp);
		sock=socket(AF_INET,SOCK_STREAM,0);
		if(hostIp!=NULL)
			addrC.sin_addr.S_un.S_addr=inet_addr(ip);
		addrC.sin_family=AF_INET;
		addrC.sin_port=htons(port);
		hostip=(char*)malloc(sizeof(char)*20);
		memset(hostip,0,sizeof(char)*20);
		hostname=(char*)malloc(sizeof(char)*30);
		memset(hostname,0,sizeof(char)*30);
	}
	~ClientTcpIp()
	{
		free(hostip);
		free(hostname);
		closesocket(sock);
		WSACleanup();
	}
	void addHostIp(const char* ip)
	{
		if(ip==NULL)
			return;
		strcpy(this->ip,ip);
		addrC.sin_addr.S_un.S_addr=inet_addr(ip);
	}
	bool tryConnect()
	{
		if(connect(sock,(SOCKADDR*)&addrC,sizeof(sockaddr))==SOCKET_ERROR)
			return false;
		return true;
	}
	inline int receiveHost(void* prec,int len)
	{
		return recv(sock,(char*)prec,len,0);
	}
	inline int sendHost(const void* psend,int len)
	{
		return send(sock,(char*)psend,len,0);
	}
	bool disconnectHost()
	{
		closesocket(sock);
		sock=socket(AF_INET,SOCK_STREAM,0);
		if(sock<=0)
			return false;
		return true;
	}
	char* getSelfIp()
	{
		char name[30]={0};
		gethostname(name,30);
		hostent* phost=gethostbyname(name);
		in_addr addr;
		char* p=phost->h_addr_list[0];
		memcpy(&addr.S_un.S_addr,p,phost->h_length);
		memset(hostip,0,sizeof(char)*20);
		memcpy(hostip,inet_ntoa(addr),strlen(inet_ntoa(addr)));
		return hostip;
	}
	char* getSelfName()
	{
		char name[30]={0};
		gethostname(name,30);
		memcpy(hostname,name,30);
		return hostname;
	}
	static bool getDnsIp(const char* name,char* ip,unsigned int ipMaxLen)
	{
		WSADATA wsa;
		if(WSAStartup(MAKEWORD(2,2),&wsa)!=0)
			return false;
		hostent* phost=gethostbyname(name);
		if(phost==NULL)
			return false;
		in_addr addr;
		char* p=phost->h_addr_list[0];
		memcpy(&addr.S_un.S_addr,p,phost->h_length);
		if(strlen(inet_ntoa(addr))>=ipMaxLen)
			return false;
		strcpy(ip,inet_ntoa(addr));
		return true;
	}
};
void getHttpBack()
{
	char ask[256]={0},url[128]={0},domain[50]={0},end[100]={0};
	int len=0;
	char* rec=(char*)malloc(sizeof(char)*10000);
	if(rec==NULL)
	{
		printf("malloc wrong");
		getchar();
		return;
	}
	memset(rec,0,sizeof(char)*10000);
	ClientTcpIp client(NULL,5206);
	DownloadFile down;
	while(1)
	{
		printf("please input the url get:\n");
		scanf("%128s",url);
		down.createAsk(url,ask);
		down.dealUrl(url,domain,end);
		printf("get domain:%s\n",domain);
		memset(end,0,sizeof(char)*100);
		if(false==ClientTcpIp::getDnsIp(domain,end,100))
			perror("ip");
		client.addHostIp(end);
		if(false==client.tryConnect())
		{
			printf("connect %s wrong\n",end);
			fflush(stdin);
			getchar();
			continue;
		}
		if((len=client.sendHost(ask,strlen(ask)))<=0)
		{
			printf("send wrong\n");
			client.disconnectHost();
			fflush(stdin);
			getchar();
			continue;
		}
		if((len=client.receiveHost(rec,10000))<=0)
		{
			printf("rec wrong\n");
			client.disconnectHost();
			fflush(stdin);
			getchar();
			continue;			
		}
		if(false==FileGet::writeToFile("recv.txt",rec,len))
		{
			printf("write wrong\n");
			client.disconnectHost();
			fflush(stdin);
			getchar();
			continue;			
		}
		printf("all success\n");
		client.disconnectHost();
	}
}
int main()
{
	getHttpBack();
}
